fix: allowed_tools=[] treated as falsy instead of disabling all tools#1
Open
fix: allowed_tools=[] treated as falsy instead of disabling all tools#1
Conversation
This PR updates the version to 0.1.21 after publishing to PyPI. ## Changes - Updated version in `pyproject.toml` to 0.1.21 - Updated version in `src/claude_agent_sdk/_version.py` to 0.1.21 - Updated `CHANGELOG.md` with release notes ## Release Information - Published to PyPI: https://pypi.org/project/claude-agent-sdk/0.1.21/ - Bundled CLI version: 2.1.15 - Install with: `pip install claude-agent-sdk==0.1.21` 🤖 Generated by GitHub Actions --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
…nthropics#488) ## Summary ### Goal: Fully Automated SDK Releases on CLI Bumps When the bundled CLI version is bumped (e.g., `chore: bump bundled CLI version to 2.1.12`), we want the SDK to automatically publish a new patch version to PyPI without any manual intervention. This PR implements that automation. ### How it works ``` Push: "chore: bump bundled CLI version to X.Y.Z" ↓ Test workflow runs (lint, tests, e2e) ↓ (on success) auto-release.yml triggers ↓ ┌─ Verify commit message + _cli_version.py changed ├─ Calculate next version: 0.1.20 → 0.1.21 ├─ Build 4 platform wheels (linux, linux-arm, macos, windows) ├─ Publish to PyPI ├─ Update _version.py, pyproject.toml ├─ Generate changelog with Claude ├─ Push directly to main (via deploy key) └─ Create git tag + GitHub Release ``` ### Changes - **`auto-release.yml`** (new): Triggers on CLI bump commits after Test workflow passes. Uses deploy key to push directly to main. - **`build-and-publish.yml`** (new): Reusable workflow for building wheels and publishing. Supports both direct-push (auto) and PR (manual) flows. - **`publish.yml`** (updated): Now calls the reusable workflow. Still available for manual releases (SDK-only changes, major/minor bumps). - Both publish flows now use the `production` environment for secrets (`DEPLOY_KEY`, `PYPI_API_TOKEN`). ### Setup Required 1. Create `production` environment in repo settings 2. Add `DEPLOY_KEY` secret (SSH deploy key with write access) 3. Move `PYPI_API_TOKEN` to production environment ## Test plan - [ ] Verify workflow syntax is valid in GitHub Actions - [ ] Test with actual CLI version bump commit - [ ] Confirm wheels build on all 4 platforms - [ ] Verify PyPI publishing and GitHub release creation ## Changelog <!-- CHANGELOG:START --> N/A - Internal CI/CD workflow changes only <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.ai/code)
…ics#504) ## Summary - Adds `contents: write` and `pull-requests: write` permissions to the `release` job in the auto-release workflow - This ensures the reusable `build-and-publish` workflow has the necessary permissions to create releases and interact with pull requests ## Test plan - [ ] Verify the auto-release workflow runs successfully on the next version bump commit - [ ] Confirm the release job can create GitHub releases and update pull requests as expected ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (100% 1-shotted by claude) Co-authored-by: Claude <noreply@anthropic.com>
## Summary Having tool_use_result on UserMessage allows for rich formatting of Claude's built-in tools in programs that use the SDK. Would love to gain access to this. Co-authored-by: Ron Mordechai <ronmrdechai@fb.com>
…ropics#511) ## Summary - The auto-release workflow's "Push to main" step could fail when the remote URL is HTTPS, as it may not have proper credentials configured. - This change explicitly sets the remote URL to the SSH endpoint (`git@github.com:anthropics/claude-agent-sdk-python.git`) before pushing, ensuring authentication works correctly with deploy keys or SSH credentials. ## Test plan - [ ] Verify the auto-release workflow triggers and successfully pushes to main using the SSH remote URL. ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (100% 9-shotted by claude) Co-authored-by: Claude <noreply@anthropic.com>
## Summary - Bumps version from 0.1.21 to 0.1.22 in `pyproject.toml` and `src/claude_agent_sdk/_version.py` - Updates `CHANGELOG.md` with new entries for features, bug fixes, and internal changes included in this release ## Test plan - [ ] Verify version strings are consistent across `pyproject.toml` and `_version.py` - [ ] Verify changelog entry is properly formatted and references correct PRs - [ ] Confirm package builds successfully with the new version ## Changelog <!-- CHANGELOG:START --> Release v0.1.22 with the following changes: - Added `tool_use_result` field to `UserMessage` (anthropics#495) - Added permissions to release job in auto-release workflow (anthropics#504) - Updated bundled Claude CLI to version 2.1.19 - Extracted build-and-publish workflow into reusable component (anthropics#488) <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (100% 11-shotted by claude) Co-authored-by: Claude <noreply@anthropic.com>
…cs#516) ## Motivation The Claude Investigator app, which uses the python claude agent SDK, needs to query MCP server connection status (example [here](https://github.com/anthropics/anthropic/blob/948dc8cc4a739b7d026d54e8da2e175cd1659340/ts-threat-intel/ts_threat_intel/claude_investigator/services/client_actor.py#L554-L557)). Currently it does this by reaching into private SDK internals: ```python if client._query and hasattr(client._query, "_send_control_request"): mcp_status_response = await client._query._send_control_request( {"subtype": "mcp_status"} ) ``` This is fragile — any SDK refactor silently breaks the caller, and the `hasattr` guard means failures degrade silently to no MCP status reporting. ## Changes Add a public `get_mcp_status()` method following the exact same pattern as `interrupt()`, `set_permission_mode()`, `set_model()`, and `rewind_files()`: - **`Query.get_mcp_status()`** — sends `{"subtype": "mcp_status"}` control request via `_send_control_request` - **`ClaudeSDKClient.get_mcp_status()`** — public wrapper with connection check, docstring with Returns and Example sections Callers can now simply do: ```python mcp_status_response = await client.get_mcp_status() ``` ## Testing The method delegates entirely to the existing `_send_control_request` infrastructure which is already tested. The new code is a 3-line wrapper with no branching logic.
Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com>
Co-Authored-By: Claude (claude-opus-4-5) <noreply@anthropic.com>
## Summary - Add `PostToolUseFailureHookInput` type with fields for `tool_name`, `tool_input`, `tool_use_id`, `error`, and optional `is_interrupt` - Add `PostToolUseFailureHookSpecificOutput` type with `additionalContext` field - Add `"PostToolUseFailure"` to `HookEvent`, `HookInput`, and `HookSpecificOutput` union types - Export new types from `__init__.py` and add to `__all__` ## Test plan - [ ] Verify `PostToolUseFailureHookInput` can be constructed with required and optional fields - [ ] Verify `PostToolUseFailureHookSpecificOutput` accepts valid output shapes - [ ] Verify type checking passes with `mypy` - [ ] Verify existing tests still pass ## Changelog <!-- CHANGELOG:START --> Added `PostToolUseFailure` hook event type for handling tool use failures, including `PostToolUseFailureHookInput` and `PostToolUseFailureHookSpecificOutput` types. <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 4-shotted by claude) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary - Add print statements to MCP e2e tests for debug visibility of message types and content - Specify `model="claude-opus-4-5"` in the permission enforcement test - Print the `executions` dict in the permission test for easier debugging ## Test plan - [ ] Run `python -m pytest e2e-tests/test_sdk_mcp_tools.py -v -s` to verify debug output appears - [ ] Confirm permission enforcement test passes with specified model ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary - Remove the `python-version` matrix from `test`, `test-e2e`, and `test-examples` CI jobs - Pin all jobs to Python 3.13 directly instead of testing across 3.10, 3.11, 3.12, and 3.13 - Reduces CI matrix size and speeds up workflow runs ## Test plan - [ ] Verify CI passes on all three OS targets (ubuntu, macos, windows) with Python 3.13 - [ ] Confirm unit tests, e2e tests, and example tests all run successfully ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 1-shotted by claude) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary - Update MCP permission enforcement e2e test to execute greet and echo tools sequentially instead of in parallel - Ensures deterministic tool call ordering for more reliable permission validation ## Test plan - [ ] Run `python -m pytest e2e-tests/test_sdk_mcp_tools.py::test_sdk_mcp_permission_enforcement` to verify the test passes with sequential execution - [ ] Confirm greet tool is called before echo tool in the test output ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 4-shotted by claude) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary - Add `RELEASING.md` documenting the automatic (CLI version bump) and manual (GitHub Actions UI) release flows - Simplify `build-and-publish.yml` to always push directly to `main` (remove PR-based release path) - Delete `create-release-tag.yml` (was only needed for the PR flow) - Drop `pull-requests: write` permission from all release workflows - Fix missing `permissions` block in `publish.yml` that was causing CI validation failure ## Test plan - [ ] Verify `publish.yml` passes workflow validation - [ ] Verify `RELEASING.md` renders correctly on GitHub --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary - Add optional `annotations` parameter to the `@tool` decorator and `SdkMcpTool` dataclass, accepting `ToolAnnotations` from the MCP types library - Pass annotations through to MCP `Tool` objects in `create_sdk_mcp_server` and include them in JSONRPC `tools/list` responses (only when set, omitted when `None`) - Re-export `ToolAnnotations` from the top-level package for convenience ## Test plan - [x] `test_tool_annotations` - Verifies annotations are stored on `SdkMcpTool` instances and flow through the MCP `list_tools` handler - [x] `test_tool_annotations_in_jsonrpc` - Verifies annotations are correctly serialized in JSONRPC `tools/list` responses and omitted when not set - [x] All 8 tests in `test_sdk_mcp_integration.py` pass - [x] `ruff check` and `ruff format` pass - [x] `mypy` has no new errors (pre-existing issues only) ## Changelog <!-- CHANGELOG:START --> - Added support for MCP tool annotations via the `@tool` decorator's new `annotations` parameter, allowing developers to specify metadata hints like `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` - Re-exported `ToolAnnotations` from `claude_agent_sdk` for convenience <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 3-shotted by claude) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…t SDK (anthropics#468) ## Summary This PR fixes the issue where large agent definitions would silently fail to register. Previously, agents were passed via the `--agents` CLI flag which has platform-specific size limits (ARG_MAX). When agents exceeded these limits, a temp file workaround with `@filepath` was used, but the CLI silently failed to parse it. ## Changes This aligns the Python SDK with the TypeScript SDK approach: - **Always use streaming mode internally** (`--input-format stream-json`) - even for string prompts - **Send agents via the initialize control request** through stdin (no size limits) - **Write string prompts to stdin** after initialize (instead of using `--print`) - **Remove the `--agents` CLI flag** and temp file handling entirely ## Why this works The TypeScript SDK always uses the control protocol with stdin/stdout. The `initialize` request is sent via stdin which has no ARG_MAX constraints, allowing arbitrarily large agent definitions. ## Testing - Added E2E tests with 260KB+ agent payloads (20 agents × 13KB prompts) - Verified agents are registered correctly in both `ClaudeSDKClient` and `query()` function - Tested WITHOUT the fix to confirm the old behavior fails silently (0/20 agents registered) - All 132 unit tests pass - All 8 E2E agent tests pass ## Before/After | Scenario | Before | After | |----------|--------|-------| | 260KB agents via `ClaudeSDKClient` | ❌ 0/20 registered (silent failure) | ✅ 20/20 registered | | 260KB agents via `query()` | ❌ 0/20 registered (silent failure) | ✅ 20/20 registered | Closes the issue raised in anthropics/claude-cli-internal#13749
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Update all GitHub Actions workflows to use `claude-opus-4-6` model - Enable explicit model selection in `claude-code-review.yml` and `claude.yml` (previously commented out) - Update model from `claude-opus-4-5` to `claude-opus-4-6` in `build-and-publish.yml` ## Test plan - [ ] Verify `build-and-publish.yml` workflow runs successfully with new model - [ ] Verify `claude-code-review.yml` workflow triggers and uses correct model on PR review - [ ] Verify `claude.yml` workflow triggers and uses correct model on issue/PR mention ## Changelog <!-- CHANGELOG:START --> <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 1-shotted by claude-opus-4-6) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Adds `ThinkingConfig` union type with `ThinkingConfigAdaptive`, `ThinkingConfigEnabled`, and `ThinkingConfigDisabled` variants - Adds `thinking` field to `ClaudeAgentOptions` that takes precedence over the deprecated `max_thinking_tokens` field - Adds `effort` field to `ClaudeAgentOptions` supporting `"low"`, `"medium"`, `"high"`, and `"max"` values, mapped to `--effort` CLI flag - Resolves `thinking` config to `--max-thinking-tokens` CLI flag: `adaptive` defaults to 32,000, `enabled` uses `budget_tokens`, `disabled` uses 0 ## Test plan - [ ] Verify `ThinkingConfigEnabled` with `budget_tokens` passes the correct value to `--max-thinking-tokens` - [ ] Verify `ThinkingConfigAdaptive` defaults to `--max-thinking-tokens 32000` when `max_thinking_tokens` is not set - [ ] Verify `ThinkingConfigDisabled` passes `--max-thinking-tokens 0` - [ ] Verify `thinking` takes precedence over `max_thinking_tokens` when both are set - [ ] Verify `effort` is passed as `--effort <value>` to the CLI - [ ] Verify all new types are exported from `__init__.py` ## Changelog <!-- CHANGELOG:START --> - Added `ThinkingConfig`, `ThinkingConfigAdaptive`, `ThinkingConfigEnabled`, and `ThinkingConfigDisabled` types to `ClaudeAgentOptions` for controlling extended thinking behavior - Added `effort` option to `ClaudeAgentOptions` for controlling thinking depth (`"low"`, `"medium"`, `"high"`, `"max"`) - Deprecated `max_thinking_tokens` in favor of the new `thinking` config field <!-- CHANGELOG:END --> 🤖 Generated with [Claude Code](https://claude.com/claude-code) (0% 11-shotted by claude) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ll tools `allowed_tools=[]` was treated as falsy and ignored, causing all tools to remain available instead of none. Change the default from `[]` to `None` and use `is not None` check to correctly pass `--allowedTools ""` to the CLI when an empty list is explicitly provided. Fixes anthropics#523 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1489baa to
97caff9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
allowed_toolsdefault from[]toNoneinClaudeAgentOptionsto distinguish "unset" from "explicitly empty"is not Noneinsubprocess_cli.pysoallowed_tools=[]correctly passes--allowedTools ""to the CLIFixes anthropics#523
Test plan
python -m mypy src/— no errorspython -m ruff check src/ tests/— all checks passedpython -m pytest tests/test_transport.py -k allowed_tools— 2 new tests passpython -m pytest tests/test_types.py— 14 tests pass (updated default assertion)python -m pytest tests/— all 131 tests pass🤖 Generated with Claude Code